/*
 * Copyright 2010-2012 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jslet.paas.modelobject.dao;

import java.util.HashMap;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.eclipse.persistence.dynamic.DynamicEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import org.jslet.paas.filter.model.FilterItem;
import org.jslet.paas.dynamichelper.BizModelHelper;
import org.jslet.paas.modelobject.test.AADao;

@Repository(value = "modelObjectDao")
public class ModelObjectDaoImpl implements ModelObjectDao
{
	private static final Logger logger = LoggerFactory.getLogger(ModelObjectDaoImpl.class);

	// private EntityManagerFactory emf;
	@PersistenceContext
	private EntityManager em;

	@Autowired
	private BizModelHelper bizObjectHelper;

	// @PersistenceUnit
	// public void setEntityManagerFactory(EntityManagerFactory emf)
	// {
	// this.emf = emf;
	// // this.em = this.emf.createEntityManager();
	// }

//	@Autowired
//	private AADao aadao;
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.jslet.paas.bizobject.dao.IBizObjectDAO#findAll(java.lang.String)
	 */
	@SuppressWarnings("unchecked")
	public List<DynamicEntity> findAll(String modelName, int pageNum, int pageSize, List<FilterItem> filters)
	{
//		this.aadao.findAll(em);
//		
//		
		
		if (logger.isDebugEnabled()){
			logger.debug("findAll:" + modelName);
		}
		Class<?> resultCls = this.bizObjectHelper.getClassByBoName(modelName);
		String jql = this.bizObjectHelper.getSelectJPQL(modelName).toString();
		Query query = em.createQuery(jql + this.convertFilterItemToJQL(filters), resultCls);
		List<DynamicEntity> result;
		if (pageSize == 0 || pageNum == 0)
		{
			result = (List<DynamicEntity>) query.getResultList();
		}
		else
		{
			int startNum = (pageNum - 1)* pageSize;
			result = (List<DynamicEntity>) query.setFirstResult(startNum).setMaxResults(pageSize).getResultList();
		}
		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.jslet.paas.bizobject.dao.IBizObjectDAO#createBizObject(java.lang.String, java.util.List)
	 */
	public void createModelObject(String modelName, List<HashMap<String, Object>> entityList)
	{
		if (entityList == null || entityList.size() == 0)
		{
			logger.warn("Empty list to create!");
			return;
		}
		DynamicEntity entity;
		for (HashMap<String, Object> mapRec : entityList)
		{
			entity = this.bizObjectHelper.createEntity(modelName);
			this.bizObjectHelper.copyFromMap(modelName, entity, mapRec, false);
			em.persist(entity);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.jslet.paas.bizobject.dao.IBizObjectDAO#updateBizObject(java.lang.String, java.util.List)
	 */
	public void updateModelObject(String modelName, List<HashMap<String, Object>> entityList)
	{
		boolean isWarnEnabled = logger.isWarnEnabled();
		if (isWarnEnabled && entityList == null || entityList.size() == 0)
		{
			logger.warn("Empty list to update!");
			return;
		}
		String keyField = this.getKeyField(modelName);
		Object value;
		Class<?> boClass = this.bizObjectHelper.getClassByBoName(modelName);
		if (boClass == null){
			throw new RuntimeException("Not found java class with biz object:" + modelName);
		}
		for (HashMap<String, Object> mapRec : entityList)
		{
			value = mapRec.get(keyField);
			DynamicEntity entity = (DynamicEntity) em.find(boClass, value);
			if (entity == null)
			{
				if (isWarnEnabled){
					logger.warn("NOT exists key:" + value + " in Database when updating!");
				}
				continue;
			}
			this.bizObjectHelper.copyFromMap(modelName, entity, mapRec, true);
			em.merge(entity);
		}
		// em.flush();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.jslet.paas.bizobject.dao.IBizObjectDAO#deleteBizObject(java.lang.String, java.util.List)
	 */
	public void deleteModelObject(String modelName, List<HashMap<String, Object>> entityList)
	{
		if (entityList == null || entityList.size() == 0)
		{
			logger.warn("Empty list to delete!");
			return;
		}
		String keyField = this.getKeyField(modelName);
		Object keyValue;
		StringBuilder sb = new StringBuilder(60);
		sb.append("delete from ").append(modelName).append(" p where p.").append(keyField).append("=?1");

		Query query = em.createQuery(sb.toString());
		for (HashMap<String, Object> recMap : entityList)
		{
			keyValue = recMap.get(keyField);
			query.setParameter(1, keyValue);
			query.executeUpdate();
		}
	}

	private String getKeyField(String modelName)
	{
		String keyField = this.bizObjectHelper.getBizObjectKeyField(modelName);
		if (keyField == null)
		{
			String msg = "NOT found key field in business object: " + modelName;
			logger.error(msg);
			throw new RuntimeException(msg);
		}
		return keyField;
	}
	
	private String convertFilterItemToJQL(List<FilterItem> filters){
		if(filters == null || filters.size() == 0){
			return "";
		}
		StringBuilder sb = new StringBuilder(" where ");
		int len = filters.size() - 1;
		for(int i = 0; i <= len; i++){
			FilterItem item = filters.get(i);
			sb.append("p.").append(item.getField()).append(" ").append(item.getOpr()).append(" \"").append(item.getValue()).append("%\"");
			if(i < len){
				sb.append(" and ");
			}
		}
		
		return sb.toString();
	}
}